package com.bolt.support.spring.jpa.query;

import org.hibernate.Session;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener;
import org.springframework.jdbc.core.BeanPropertyRowMapper;

import javax.persistence.EntityManager;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Created by Administrator on 2017/8/18.
 */
public class BeanPropertyAndPostLoadRowMapper extends BeanPropertyRowMapper {

    private final JdbcQueryMethod method;

    private final EntityManager entityManager;

    public BeanPropertyAndPostLoadRowMapper( EntityManager entityManager,JdbcQueryMethod method) {
        super(method.getReturnedObjectType());
        this.method = method;
        this.entityManager = entityManager;
    }

    protected Session getSession() {
        Session session = entityManager.unwrap(Session.class);
        return session;
    }

    protected  void onLoad(SharedSessionContractImplementor session, PostLoadEvent postLoadEvent) {
        final EventListenerGroup<PostLoadEventListener> listenerGroup = session.getFactory()
                .getServiceRegistry()
                .getService( EventListenerRegistry.class )
                .getEventListenerGroup( EventType.POST_LOAD );

        for (PostLoadEventListener listener : listenerGroup.listeners()) {
            listener.onPostLoad(postLoadEvent);
        }
    }

    @Override
    public Object mapRow(ResultSet rs, int rowNum) throws SQLException{
        Object mappedObject  =  super.mapRow(rs,rowNum);
        if(this.method.hasEntityListeners()){
            SharedSessionContractImplementor session = getSession().unwrap(SharedSessionContractImplementor.class);
            PostLoadEvent postLoadEvent = new PostLoadEvent((EventSource)session);
            postLoadEvent.setEntity(mappedObject);
            onLoad(session,postLoadEvent);
        }
        return mappedObject;
    }

}
